﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Text;
using System.Reflection;
using System.Data.Linq.Mapping;
using BulletOnRails4NET.Models;

namespace BulletOnRails4NET.Controllers
{
    public class FormHelper
    {
        static String[] _genders = new String[] { "M", "F" };

        //Populates the model with information provided in the form collection
        public static List<RuleViolation> PopulateProperties(object obj, FormCollection form_fields)
        {
            string field_name;
            List<RuleViolation> violations = new List<RuleViolation>();
            //bool is_valid = true;
            Type type = obj.GetType();
            object[] info;
            PropertyInfo[] properties = type.GetProperties();
            string[] keys = form_fields.AllKeys;

            foreach (PropertyInfo prop in properties)
            {
                //Get the Linq realted info
                info = prop.GetCustomAttributes(typeof(ColumnAttribute), true);
                // Check if it is a Linq column property
                if (info.Length == 1)
                {
                    ColumnAttribute ca = (ColumnAttribute)info[0];
                    field_name = prop.Name;
                    if (keys.Contains(field_name))
                    {
                        violations.AddRange(RuleViolation.CheckBasicDBCobnstraints(obj, prop, ca, form_fields[field_name], true));

                    }
                }
            }
            return violations;
        }

        public static void AppendGenderSelectField(HtmlHelper html_helper, StringBuilder builder, string field_name, string str_prop_value)
        {
            SelectList gender_list_box = new SelectList(_genders, str_prop_value);
            builder.Append(html_helper.DropDownList(field_name, gender_list_box));
        }

        // Checks that fields required fields in the database (not null flagged) are present
        // * checks that values are numbers for numeric fields
        // * Checks that string values are not too big for the db field
        public static string CreateFormFieldsFromDBFields(HtmlHelper html_helper, object obj, PropertyInfo[] editable_properties, Dictionary<string, string> overriden_fields_with_code)
        {
            ColumnAttribute ca;
            StringBuilder builder = new StringBuilder(255);
            String field_name;
            Type type = obj.GetType();
            object[] info;
            PropertyInfo[] properties;
            if (editable_properties == null)
                properties = type.GetProperties();
            else
                properties = editable_properties;
            foreach (PropertyInfo prop in properties)
            {
                //Get the Linq realted info
                info = prop.GetCustomAttributes(typeof(ColumnAttribute), true);
                // Check if it is a Linq column property
                if (info.Length == 1)
                {
                    ca = (ColumnAttribute)info[0];
                    if (!ca.IsDbGenerated)
                    {
                        field_name = prop.Name;
                        if (overriden_fields_with_code == null || !overriden_fields_with_code.ContainsKey(field_name))
                        {
                            string dbtype = ca.DbType;
                            string str_prop_value = "";
                            object prop_value = prop.GetValue(obj, null);
                            if (prop_value != null)
                                str_prop_value = prop_value.ToString();

                            

                            builder.Append("<p>");
                            builder.Append("<label for=\"");
                            builder.Append(field_name);
                            builder.Append("\">");
                            builder.Append(field_name.HumanizeString());
                            builder.Append("</label>");

                            //Put html type of field depending on the column name or type
                            if (field_name.ToLower().Contains("password"))
                            {
                                builder.Append(html_helper.Password(field_name));
                            }
                            else if (dbtype.Contains("Text"))
                            {
                                builder.Append(html_helper.TextArea(field_name, str_prop_value));
                            }
                            else if (field_name.ToLower().Contains("gender")) //TODO check if it is a one char field
                            {
                                AppendGenderSelectField(html_helper, builder, field_name, str_prop_value);
                            }
                            else
                            {
                                builder.Append(html_helper.TextBox(field_name, str_prop_value));
                            }
                            builder.Append(html_helper.ValidationMessage(field_name, "*"));
                            builder.Append("</p>");
                        }
                        else
                        {
                            builder.Append(overriden_fields_with_code[field_name]);
                        }
                    }
                }
            }
            return builder.ToString();
        }

        // Creates the detils page for a record
        public static string CreateDetailsFromDBFields(HtmlHelper html_helper, object obj, PropertyInfo[] editable_properties, Dictionary<string, string> overriden_fields_with_code)
        {
            ColumnAttribute ca;
            StringBuilder builder = new StringBuilder(255);
            String field_name;
            Type type = obj.GetType();
            object[] info;
            PropertyInfo[] properties;
            if (editable_properties == null)
                properties = type.GetProperties();
            else
                properties = editable_properties;
            foreach (PropertyInfo prop in properties)
            {
                //Get the Linq realted info
                info = prop.GetCustomAttributes(typeof(ColumnAttribute), true);
                // Check if it is a Linq column property
                if (info.Length == 1)
                {
                    ca = (ColumnAttribute)info[0];
                        field_name = prop.Name;
                        if (overriden_fields_with_code == null || overriden_fields_with_code.ContainsKey(field_name))
                        {
                            string dbtype = ca.DbType;
                            string str_prop_value = "";
                            object prop_value = prop.GetValue(obj, null);
                            if (prop_value != null)
                                str_prop_value = prop_value.ToString();

                            builder.Append("<p>");
                            builder.Append(field_name.HumanizeString());
                            builder.Append(":");

                            //Put html depending on the column name
                            if (!field_name.ToLower().Contains("password"))
                            {
                                builder.Append(html_helper.Encode(str_prop_value));
                            }
                            builder.Append("</p>");
                        }
                        else
                        {
                            builder.Append(overriden_fields_with_code[field_name]);
                        }
                }
            }
            return builder.ToString();
        }

    }
}
